home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / rclesrc.10 / ircle sources / InputLine.p < prev    next >
Encoding:
Text File  |  1992-09-06  |  8.6 KB  |  428 lines

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: InputLine    }
  3. {    Copyright ⌐ 1992 Olaf Titz (s_titz@iravcl.ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit InputLine;
  20. { Provides a small window with status and input lines. }
  21. { All keystrokes go into the input line. Implements a command history.}
  22.  
  23. interface
  24. uses
  25.     ApplBase;
  26.  
  27. procedure InitInputLine;
  28. { Startup }
  29.  
  30. procedure OpenInputLine (process: ProcPtr);
  31. { Open the input line window }
  32. { process(var s:string) gets called whenever Return was pressed }
  33.  
  34. procedure SetInputLine (var s: string);
  35. { Preset the input line }
  36.  
  37. procedure InsertInputLine (var s: string);
  38. { Insert a string into the input line }
  39.  
  40. procedure StatusLine (var s: string);
  41. { Set the status line }
  42.  
  43. procedure CloseInputLine;
  44. { Close the window }
  45.  
  46. implementation
  47.  
  48. const
  49.     MAXHIST = 5000;    { Maximum # of chars to store in command history }
  50.     MAXLINE = 240;        { Maximum length of input line }
  51.  
  52. var
  53.     iw: WindowPtr;
  54.     Hact, Hupd, Hmouse, Hkey, Hakey, Hidle, Hpaste: integer;
  55.     status, line: string;
  56.     procs: ProcPtr;
  57.     line1, line2, letterw: integer;
  58.     CursorRect: Rect;
  59.     LeftMargin, Cursor: integer;
  60.     blink: longint;
  61.     bls, ReturnHit: boolean;
  62.     hist: CharsHandle;
  63.     hpos: integer;
  64.  
  65. procedure initInputLine;
  66.     var
  67.         i: integer;
  68.     begin
  69.         iw := nil;
  70.         hist := CharsHandle(NewHandle(1));
  71.         hist^^[0] := chr(0);
  72.         hpos := 0;
  73.     end;
  74.  
  75. procedure DoRedraw (l: integer);
  76.     var
  77.         p0: GrafPtr;
  78.     begin
  79.         GetPort(p0);
  80.         SetPort(iw);
  81.         if l = 1 then begin
  82.             MoveTo(1, line1);
  83.             DrawString(status);
  84.         end
  85.         else begin
  86.             MoveTo(1, line2);
  87.             DrawText(@line, LeftMargin + 1, 80);
  88.         end;
  89.         SetPort(p0);
  90.     end;
  91.  
  92. procedure StackupLine;
  93.     var
  94.         i: integer;
  95.     begin
  96.         if gethandlesize(Handle(hist)) > MAXHIST then begin
  97.             i := 1;
  98.             while hist^^[i] <> chr(0) do
  99.                 i := succ(i);
  100.             i := Munger(Handle(hist), 1, nil, i, ptr(1), 0);
  101.         end;
  102.         i := length(line) + 1;
  103.         if i > 1 then begin
  104.             line[i] := chr(0);
  105.             i := PtrAndHand(@line[1], Handle(hist), i);
  106.             hpos := gethandlesize(Handle(hist)) - 1;
  107.         end
  108.     end;
  109.  
  110. procedure RecallLine (p: integer);
  111.     var
  112.         i: integer;
  113.         s: string;
  114.     begin
  115.         hpos := p;
  116.         i := 0;
  117.         repeat
  118.             p := succ(p);
  119.             i := succ(i);
  120.             s[i] := hist^^[p];
  121.         until s[i] = chr(0);
  122.         s[0] := chr(i - 1);
  123.         SetInputLine(s);
  124.     end;
  125.  
  126. procedure RecallLineUp;
  127.     var
  128.         i: integer;
  129.     begin
  130.         i := hpos;
  131.         if i > 0 then begin
  132.             repeat
  133.                 i := pred(i)
  134.             until hist^^[i] = chr(0);
  135.             RecallLine(i);
  136.         end
  137.     end;
  138.  
  139. procedure RecallLineDown;
  140.     var
  141.         i: integer;
  142.         s: string[1];
  143.     begin
  144.         i := hpos;
  145.         if i < gethandlesize(handle(hist)) - 1 then begin
  146.             repeat
  147.                 i := succ(i)
  148.             until hist^^[i] = chr(0);
  149.             if i < gethandlesize(handle(hist)) - 1 then
  150.                 RecallLine(i)
  151.             else begin
  152.                 s := '';
  153.                 SetInputLine(s);
  154.             end;
  155.         end;
  156.     end;
  157.  
  158.  
  159. procedure SetCursor (n: integer);
  160.     begin
  161.         if n < 1 then
  162.             n := 1
  163.         else if n > MAXLINE then
  164.             n := MAXLINE;
  165.         if leftMargin > n - 1 then
  166.             leftMargin := n - 1
  167.         else if leftMargin < n - 81 then
  168.             leftmargin := n - 81;
  169.         EraseRect(CursorRect);
  170.         Cursor := n;
  171.         SetRect(CursorRect, (Cursor - LeftMargin - 1) * letterw, line1 + 3, (Cursor - LeftMargin - 1) * letterw + 1, line2 + 2);
  172.         bls := true;
  173.         blink := maxlongint;
  174.         DoRedraw(2);
  175.     end;
  176.  
  177.  
  178. function Activate (var e: EventRecord): boolean;
  179.     begin
  180.         if iw <> nil then
  181.             if bitand(e.message, 1) = 1 then
  182.                 ShowWindow(iw)
  183.             else
  184.                 HideWindow(iw);
  185.         Activate := false
  186.     end;
  187.  
  188. function Update (var e: EventRecord): boolean;
  189.     begin
  190.         if WindowPtr(e.message) = iw then begin
  191.             BeginUpdate(iw);
  192.             MoveTo(1, line1);
  193.             DrawString(status);
  194.             MoveTo(1, line2);
  195.             DrawText(@line, LeftMargin + 1, 80);
  196.             EndUpdate(iw);
  197.             Update := true
  198.         end
  199.         else
  200.             Update := false
  201.     end;
  202.  
  203. function Mouse (var e: EventRecord): boolean;
  204.     begin
  205.         if WindowPtr(e.message) = iw then begin
  206.             GlobalToLocal(e.where);
  207.             SetCursor(e.where.h div letterw + 1 + LeftMargin);
  208.             Mouse := true
  209.         end
  210.         else
  211.             Mouse := false
  212.     end;
  213.  
  214. procedure SCALL (var s: string; p: ProcPtr);
  215. inline
  216.     $205F, $4E90;        { movea.l (a7)+,a0; jsr (a0) }
  217.  
  218. procedure GotLine;
  219.     var
  220.         i: integer;
  221.     begin
  222.         ReturnHit := true;
  223.         i := 255;
  224.         while (i > 0) and (line[i] = ' ') do
  225.             i := pred(i);
  226.         line[0] := chr(i);
  227.         StackupLine;
  228.         SCALL(line, procs);
  229.         line := '';
  230.         SetInputLine(line);
  231.         ReturnHit := false;
  232.     end;
  233.  
  234.  
  235. function Key (var e: EventRecord): boolean;
  236.     var
  237.         c: char;
  238.         i: integer;
  239.         p0: GrafPtr;
  240.     begin
  241.         if iw = nil then
  242.             Key := false
  243.         else begin
  244.             getPort(p0);
  245.             SetPort(iw);
  246.             c := chr(e.message mod 256);
  247.             case ord(c) of
  248.                 8: 
  249.                     if cursor > 1 then begin
  250.                         for i := cursor - 1 to MAXLINE - 1 do
  251.                             line[i] := line[i + 1];
  252.                         line[MAXLINE] := ' ';
  253.                         SetCursor(pred(cursor));
  254.                     end;
  255.                 13: 
  256.                     GotLine;
  257.                 28: 
  258.                     SetCursor(pred(cursor));
  259.                 29: 
  260.                     SetCursor(succ(cursor));
  261.                 30: 
  262.                     RecallLineUp;
  263.                 31: 
  264.                     RecallLineDown;
  265.                 otherwise
  266.                     begin
  267.                     if cursor < MAXLINE then begin
  268.                         for i := MAXLINE downto cursor + 1 do
  269.                             line[i] := line[i - 1];
  270.                         line[cursor] := c;
  271.                         SetCursor(succ(cursor));
  272.                     end;
  273.                 end;
  274.             end;
  275.             SetPort(p0);
  276.         end;
  277.         Key := true;
  278.     end;
  279.  
  280. function AKey (var e: EventRecord): boolean;
  281.     begin
  282.         AKey := Key(e)
  283.     end;
  284.  
  285. function Idle (var e: EventRecord): boolean;
  286.     var
  287.         p0: GrafPtr;
  288.     begin
  289.         if abs(e.when - blink) > GetCaretTime then begin
  290.             GetPort(p0);
  291.             SetPort(iw);
  292.             bls := not bls;
  293.             blink := e.when;
  294.             penMode(patXor);
  295.             PaintRect(CursorRect);
  296.             SetPort(p0);
  297.         end;
  298.         Idle := false;
  299.     end;
  300.  
  301. function Paste (var e: EventRecord): boolean;
  302.     var
  303.         h: CharsHandle;
  304.         i, n, c: integer;
  305.         f: EventRecord;
  306.         b: boolean;
  307.     begin
  308.         if e.message = 5 then begin
  309.             i := TEFromScrap;
  310.             h := CharsHandle(TEScrapHandle);
  311.             n := TEGetScrapLen;
  312.             for i := 0 to n - 1 do begin
  313.                 c := ord(h^^[i]);
  314.                 f.message := c;
  315.                 b := Key(f);
  316.                 if c = 13 then
  317.                     repeat
  318.                         ApplRun
  319.                     until not ReturnHit;
  320.             end;
  321.             Paste := true
  322.         end
  323.         else
  324.             Paste := false
  325.     end;
  326.  
  327. procedure OpenInputLine (process: ProcPtr);
  328.     var
  329.         p0: GrafPtr;
  330.         fi: FontInfo;
  331.         r: Rect;
  332.         i: integer;
  333.     begin
  334.         if iw = nil then begin
  335.             for i := 1 to 255 do begin
  336.                 Status[i] := ' ';
  337.                 line[i] := ' '
  338.             end;
  339.             Status[0] := chr(255);
  340.             line[0] := chr(255);
  341.             LeftMargin := 0;
  342.             SetRect(r, 0, 0, 16, 16);
  343.             iw := NewWindow(nil, r, '', false, 3, WindowPtr(-1), false, 0);
  344.             if iw <> nil then begin
  345.                 GetPort(p0);
  346.                 SetPort(iw);
  347.                 SetOrigin(-2, -2);
  348.                 penMode(patXor);
  349.                 TextFont(monaco);
  350.                 TextSize(9);
  351.                 TextFace([]);
  352.                 TextMode(srcCopy);
  353.                 GetFontInfo(fi);
  354.                 line1 := fi.ascent + fi.leading;
  355.                 line2 := line1 + fi.descent + fi.leading + fi.ascent + 1;
  356.                 SetRect(CursorRect, 0, 0, 0, 0);
  357.                 letterw := fi.widMax;
  358.                 blink := -maxlongint;
  359.                 bls := false;
  360.                 SizeWindow(iw, 80 * letterw + 4, line2 + fi.descent + fi.leading + 6, true);
  361.                 with screenBits.bounds do
  362.                     MoveWindow(iw, (right - left - iw^.portRect.right + 2) div 2 - 1, bottom - iw^.portRect.bottom - 5, true);
  363.                 Hact := ApplTask(@Activate, app4Evt);
  364.                 Hupd := ApplTask(@Update, updateEvt);
  365.                 Hmouse := ApplTask(@Mouse, mouseMsg + inContent);
  366.                 Hkey := ApplTask(@Key, keyDown);
  367.                 Hakey := ApplTask(@Akey, autoKey);
  368.                 Hidle := ApplTask(@Idle, nullEvent);
  369.                 Hpaste := ApplTask(@Paste, menuMsg + editMenu);
  370.                 SetCursor(0);
  371.                 SetPort(p0);
  372.                 ShowWindow(iw);
  373.                 procs := process;
  374.             end
  375.         end;
  376.     end;
  377.  
  378. procedure StatusLine (var s: string);
  379.     begin
  380.         status := s;
  381.         DoRedraw(1);
  382.     end;
  383.  
  384. procedure SetInputLine (var s: string);
  385.     var
  386.         i: integer;
  387.         p0: GrafPtr;
  388.     begin
  389.         if iw <> nil then begin
  390.             GetPort(p0);
  391.             SetPort(iw);
  392.             line := s;
  393.             SetCursor(length(line) + 1);
  394.             for i := length(line) + 1 to 255 do
  395.                 line[i] := ' ';
  396.             line[0] := chr(255);
  397.             DoRedraw(2);
  398.             SetPort(p0)
  399.         end
  400.     end;
  401.  
  402.  
  403. procedure InsertInputLine (var s: string);
  404.     var
  405.         i: integer;
  406.         f: EventRecord;
  407.         b: boolean;
  408.     begin
  409.         for i := 1 to length(s) do begin
  410.             f.message := ord(s[i]);
  411.             b := Key(f);
  412.         end;
  413.     end;
  414.  
  415. procedure CloseInputLine;
  416.     begin
  417.         ApplUntask(Hact);
  418.         ApplUntask(Hupd);
  419.         ApplUntask(Hmouse);
  420.         ApplUntask(Hkey);
  421.         ApplUntask(Hakey);
  422.         ApplUntask(Hidle);
  423.         ApplUNtask(Hpaste);
  424.         DisposeWindow(iw);
  425.         iw := nil
  426.     end;
  427.  
  428. end.